import { baseGetUploadSign } from "@/service/modules/base";
import { getEnvValue } from "@/utils/env";
import Cos, { CosError } from "cos-js-sdk-v5";

//文件上传参数
export interface IUploadOptions {
	// 文件
	Body: File;
	// 文件名称
	FileName?: string;
	// 文件路径
	Path?: string;
	// 返回的url地址类型 (默认cdn)
	urlType?: "cdn" | "original";
}
/**
 * 上传文件到cos
 */
export const useCosUpload = () => {
	//默认参数
	const defaultOptions: Cos.ObjectParams = {
		//存储桶名称
		Bucket: getEnvValue("ENV_COS_BUCKET") + "-" + getEnvValue("ENV_COS_APPID"),
		//存储桶所在地域
		Region: getEnvValue("ENV_COS_REGION"),
		//文件的基础目录
		Key: getEnvValue("ENV_COS_KEY")
	};

	//生成cos对象
	const cos = new Cos({
		// 同一个实例下上传的文件并发数，默认值3
		FileParallelLimit: 5,
		// 同一个上传文件的分块并发数，默认值3
		ChunkParallelLimit: 5,
		// 签名方法
		getAuthorization: async (options, callback) => {
			const { data } = await baseGetUploadSign();

			callback({
				TmpSecretId: data.credentials.tmpSecretId,
				TmpSecretKey: data.credentials.tmpSecretKey,
				SecurityToken: data.credentials.sessionToken,
				StartTime: data.startTime,
				ExpiredTime: data.expiredTime
			});
		}
	});

	/**
	 *校验文件名
	 * @param options
	 * @returns
	 */
	const checkFileName = (options: IUploadOptions) => {
		// 判断是否自定义文件名 如未填写直接使用文件名称
		if (options.FileName) return options.FileName + options.Body.name.match(/.[^.]+$/)[0];
		else return options.Body.name;
	};

	/**
	 * 高级上传文件
	 * @param {IUploadOptions} options
	 * @param {Function} progressCallback
	 * @returns {string} 文件地址
	 */
	const cosUpLoadFile = async (options: IUploadOptions, progressCallback?: (progressInfo: Cos.ProgressInfo) => any) => {
		// 生成文件名称
		const fileName = checkFileName(options);
		// 生成文件路径
		const Key = defaultOptions.Key + options.Path + fileName;
		// 生成上传文件对象
		const putOptions: Cos.UploadFileParams = {
			...defaultOptions,
			...options,
			//触发分块上传的阈值，超过5MB使用分块上传
			SliceSize: 1024 * 1024 * 5,
			onProgress: progressCallback,
			Key
		};
		try {
			const { Location } = await cos.uploadFile(putOptions);
			return "https://" + Location;
			// return options.urlType == "original" ? "https://" + Location : cosPrefix + options.Path + fileName;
		} catch (error) {
			console.log(error);
			ElNotification.error({
				title: "提示",
				message: (<CosError>error).code + (<CosError>error).message
			});
		}
	};

	/**
	 * 高级上传多文件   暂时不需要 有问题 不要使用
	 * @param {IUploadOptions} options
	 * @param {Function} progressCallback
	 * @returns {string[]} 文件地址数组
	 */
	const cosUpLoadFiles = async (options: IUploadOptions[], progressCallback?: (progressInfo: Cos.ProgressInfo) => any) => {
		// 生成文件名称
		options.forEach(item => {
			item.FileName = checkFileName(item);
			// 生成文件路径
			defaultOptions.Key = defaultOptions.Key + item.Path + item.FileName;
			item = { ...item, ...defaultOptions };
		});

		// 生成上传文件对象
		const putOptions: Cos.UploadFilesParams = {
			files: options as Cos.UploadFileItemParams[],
			//触发分块上传的阈值，超过5MB使用分块上传
			SliceSize: 1024 * 1024 * 20,
			onProgress: progressCallback
		};
		try {
			const resp = await cos.uploadFiles(putOptions);

			return resp.files.map(item => item.data.Location);
		} catch (error) {
			console.log(error);

			ElNotification.error({
				title: "提示",
				message: (<CosError>error).code + (<CosError>error).message
			});
		}
	};

	/**
	 * 普通上传文件
	 * @param {IUploadOptions} options
	 * @param {Function} progressCallback
	 * @returns {string} 文件地址
	 */
	const cosPutObject = async (options: IUploadOptions, progressCallback?: (progressInfo: Cos.ProgressInfo) => any) => {
		// 生成文件名称
		const fileName = checkFileName(options);
		// 生成文件路径
		const Key = defaultOptions.Key + options.Path + fileName;
		// 生成上传文件对象
		const putOptions: Cos.PutObjectParams = {
			...defaultOptions,
			...options,
			onProgress: progressCallback,
			Key
		};
		try {
			const { Location } = await cos.putObject(putOptions);
			return "https://" + Location;
		} catch (error) {
			ElNotification.error({
				title: "提示",
				message: (<CosError>error).code + (<CosError>error).message
			});
		}
	};

	/**
	 * 分片上传文件
	 * @param {IUploadOptions} options
	 * @param {Function} progressCallback
	 * @returns {string} 文件地址
	 */
	const cosSliceUpload = async (options: IUploadOptions, progressCallback?: (progressInfo: Cos.ProgressInfo) => any) => {
		// 生成文件名称
		const fileName = checkFileName(options);
		// 生成文件路径
		const Key = defaultOptions.Key + options.Path + fileName;
		// 生成上传文件对象
		const putOptions: Cos.SliceUploadFileParams = {
			...defaultOptions,
			...options,
			onProgress: progressCallback,
			Key
		};

		try {
			const { Location } = await cos.sliceUploadFile(putOptions);
			return "https://" + Location;
		} catch (error) {
			ElNotification.error({
				title: "提示",
				message: (<CosError>error).code + (<CosError>error).message
			});
		}
	};

	return { cosPutObject, cosSliceUpload, cosUpLoadFile, cosUpLoadFiles };
};
